import { _decorator, Component, director, Node } from 'cc';
import Levels from '../../levels'
import { ILevel } from '../../levels';
import DataManager, { IRecord } from '../../Runtime/DataManager';
import { createUINode } from '../../Utils';
import { TILE_HEIGHT, TILE_WIDTH, TileManager } from '../Tile/TileManager';
import { TileMapManger } from '../Tile/TileMapManger';
import EventManager from '../../Runtime/EventManger';
import { DIRECTION_ENUM, ENTITY_STATE_ENUM, ENTITY_TYPE_ENUM, EVENT_ENUM, SCENE_ENUM } from '../../Enums';
import { PlayerManager } from '../Player/playerManager';
import { WoodenSkeletonManager } from '../WoodenSkeleton/WoodenSkeletonMananger';
import { DoorManager } from '../Door/DoorManager';
import { IEntity } from '../../levels';
import { IronSkeletonManager } from '../IronSkeleton/IronSkeletonManager';
import { BurstManager } from '../Burst/BurstManager';
import { SpikesManager } from '../Spikes/SpikesManager';
import { SmokeManager } from '../Smoke/SmokeManager';
import FaderManager from '../../Runtime/FaderManager';
import { ShakeManager } from '../UI/ShakeManager';
const { ccclass, property } = _decorator;

@ccclass('BattleManager')
export class BattleManager extends Component {
  level:ILevel
  stage:Node
  private smokeLayer:Node
  private inited=false

  onLoad(){
    DataManager.Instance.levelIndex=1
    EventManager.Instance.on(EVENT_ENUM.NEXT_LEVEL,this.nextLevel,this)
    EventManager.Instance.on(EVENT_ENUM.PLAYER_MOVE_END,this.checkArrived,this)
    EventManager.Instance.on(EVENT_ENUM.SHOW_SMOKE,this.generateSmoke,this)
    EventManager.Instance.on(EVENT_ENUM.RECORD_STEP,this.record,this)
    EventManager.Instance.on(EVENT_ENUM.REVOKE_STEP,this.revoke,this)
    EventManager.Instance.on(EVENT_ENUM.RESTART_LEVEL,this.initLevel,this)
    EventManager.Instance.on(EVENT_ENUM.OUT_BATTLE,this.outBattle,this)
  }

  onDestroy(){
    EventManager.Instance.off(EVENT_ENUM.NEXT_LEVEL,this.nextLevel)
    EventManager.Instance.off(EVENT_ENUM.PLAYER_MOVE_END,this.checkArrived)
    EventManager.Instance.off(EVENT_ENUM.SHOW_SMOKE,this.generateSmoke)
    EventManager.Instance.off(EVENT_ENUM.RECORD_STEP,this.record)
    EventManager.Instance.off(EVENT_ENUM.REVOKE_STEP,this.revoke)
    EventManager.Instance.off(EVENT_ENUM.RESTART_LEVEL,this.initLevel)
    EventManager.Instance.off(EVENT_ENUM.OUT_BATTLE,this.outBattle)
  }

  start() {
      this.generateStage()
      this.initLevel()
  }

  update(deltaTime: number) {

  }

  async initLevel() {
    const level = Levels[`level${DataManager.Instance.levelIndex}`]
    console.log("levelIndex值:", DataManager.Instance.levelIndex);
    console.log("levelIndex类型:", typeof DataManager.Instance.levelIndex);
    if (level) {
      if(this.inited){
        await FaderManager.Instance.fadeIn()
      }else{
        await FaderManager.Instance.mask()
      }
      this.clearLevel()
      this.level = level

      DataManager.Instance.mapInfo = this.level.mapInfo
      DataManager.Instance.mapRowCount = this.level.mapInfo.length || 0
      DataManager.Instance.mapColumnCount = this.level.mapInfo[0].length||0

      await Promise.all([
        this.generateTileMap(),
        this.generateBurst(),
        this.generateSpikes(),
        this.generateDoor(),
        this.generateEnemies(),
        this.generateSmokeLayer(),//保证烟雾层在角色上面
        this.generatePlayer(),
      ])

      await FaderManager.Instance.fadeOut()
      this.inited=true
    }else{
      this.outBattle()
    }
  }

  async outBattle(){
    await FaderManager.Instance.fadeIn()
    director.loadScene(SCENE_ENUM.Start)
  }

  nextLevel(){
    DataManager.Instance.levelIndex++
    this.initLevel()
  }

  clearLevel(){
    this.stage.destroyAllChildren()
    DataManager.Instance.reset()
  }

  generateStage() {
    // 创建舞台节点
    this.stage = createUINode()
    this.stage.setParent(this.node)
    this.stage.addComponent(ShakeManager)
    this.stage.getComponent(ShakeManager).init()
  }

  async generateTileMap() {
    // 创建瓦片地图并初始化
    const tileMap = createUINode()
    tileMap.setParent(this.stage)
    const tileMapManger = tileMap.addComponent(TileMapManger)
    await tileMapManger.init()

    this.adaptPos()
  }

  async generatePlayer(){
    const player = createUINode()
    player.setParent(this.stage)
    const playerManager=player.addComponent(PlayerManager)
    await playerManager.init(this.level.player)
    DataManager.Instance.player=playerManager
    EventManager.Instance.emit(EVENT_ENUM.PLAYER_BORN,true)
  }

  async generateEnemies(){
    const promise=[]
    for(let i=0;i<this.level.enemies.length;++i){
      const enemy=this.level.enemies[i]
      const node = createUINode()
      node.setParent(this.stage)
      const Manager=enemy.type===ENTITY_TYPE_ENUM.SKELETON_WOODEN?WoodenSkeletonManager:IronSkeletonManager;
      const manager=node.addComponent(Manager)
      promise.push(manager.init(enemy))
      DataManager.Instance.enemies.push(manager)
    }
    //await提出来，使加载更快
    await Promise.all(promise)
  }

  async generateDoor(){
    const door = createUINode()
    door.setParent(this.stage)
    const doorManager=door.addComponent(DoorManager)
    await doorManager.init(this.level.door)
    DataManager.Instance.door=doorManager
  }

  async generateBurst(){
    const promise=[]
    for(let i=0;i<this.level.bursts.length;++i){
      const burst=this.level.bursts[i]
      const node = createUINode()
      node.setParent(this.stage)
      const burstManager=node.addComponent(BurstManager)
      promise.push(burstManager.init(burst))
      DataManager.Instance.bursts.push(burstManager)
    }
    //await提出来，使加载更快
    await Promise.all(promise)
  }

  async generateSpikes(){
    const promise=[]
    for(let i=0;i<this.level.spikes.length;++i){
      const spikes=this.level.spikes[i]
      const node = createUINode()
      node.setParent(this.stage)
      const spikesManager=node.addComponent(SpikesManager)
      promise.push(spikesManager.init(spikes))
      DataManager.Instance.spikes.push(spikesManager)
    }
    //await提出来，使加载更快
    await Promise.all(promise)
  }

  async generateSmoke(x:number,y:number,direction:DIRECTION_ENUM){
    const item=DataManager.Instance.smokes.find(smoke=>smoke.state===ENTITY_STATE_ENUM.DEATH)
    if(item){
      item.x=x
      item.y=y
      item.node.setPosition(
        x * TILE_WIDTH - 1.5 * TILE_WIDTH,
        y * TILE_HEIGHT + 1.5 * TILE_HEIGHT
      )
      item.direction=direction
      item.state=ENTITY_STATE_ENUM.IDLE
    }else{
      const smoke = createUINode()
      smoke.setParent(this.smokeLayer)
      const smokeManager=smoke.addComponent(SmokeManager)
      await smokeManager.init({
        x,
        y,
        direction,
        state:ENTITY_STATE_ENUM.IDLE,
        type:ENTITY_TYPE_ENUM.SMOKE
      })
      DataManager.Instance.smokes.push(smokeManager)
    }
  }

  async generateSmokeLayer(){
    this.smokeLayer = createUINode()
    this.smokeLayer.setParent(this.stage)
  }

  checkArrived(){
    if(!DataManager.Instance.player||!DataManager.Instance.door){
      return
    }
    const {x:playerX,y:playerY}=DataManager.Instance.player
    const {x:doorX,y:doorY,state:doorState}=DataManager.Instance.door
    if(playerX===doorX&&playerY===doorY&&doorState===ENTITY_STATE_ENUM.DEATH){
      EventManager.Instance.emit(EVENT_ENUM.NEXT_LEVEL)
    }
  }

  adaptPos() {
    // 调整舞台位置使地图居中
    const { mapRowCount, mapColumnCount } = DataManager.Instance
    const disX = TILE_WIDTH * mapRowCount / 2
    const disY = TILE_HEIGHT * mapColumnCount / 2
    this.stage.getComponent(ShakeManager).stop()
    this.stage.setPosition(-disX,disY)
  }

  record(){
    const item:IRecord = {
      player: {
        x: DataManager.Instance.player.x,
        y: DataManager.Instance.player.y,
        direction: DataManager.Instance.player.direction,
        state: DataManager.Instance.player.state === ENTITY_STATE_ENUM.IDLE ||
          DataManager.Instance.player.state === ENTITY_STATE_ENUM.DEATH ||
          DataManager.Instance.player.state === ENTITY_STATE_ENUM.AIRDEATH
          ? DataManager.Instance.player.state
          : ENTITY_STATE_ENUM.IDLE,
        type: DataManager.Instance.player.type,
      },
      door: {
        x: DataManager.Instance.door.x,
        y: DataManager.Instance.door.y,
        direction: DataManager.Instance.door.direction,
        state: DataManager.Instance.door.state,
        type: DataManager.Instance.door.type,
      },
      enemies: DataManager.Instance.enemies.map(({ x, y, direction, state, type }) => ({
        x,
        y,
        direction,
        state,
        type,
      })),
      bursts: DataManager.Instance.bursts.map(({ x, y, direction, state, type }) => ({
        x,
        y,
        direction,
        state,
        type,
      })),
      spikes: DataManager.Instance.spikes.map(({ x, y, count, type }) => ({
        x,
        y,
        count,
        type ,
      })),
    }
    DataManager.Instance.records.push(item)
  }

  revoke(){
    const item=DataManager.Instance.records.pop()
    if(item){
      // 恢复玩家状态
      DataManager.Instance.player.x = DataManager.Instance.player.targetX = item.player.x;
      DataManager.Instance.player.y = DataManager.Instance.player.targetY = item.player.y;
      DataManager.Instance.player.direction = item.player.direction;
      DataManager.Instance.player.state = item.player.state;

      // 恢复门状态
      DataManager.Instance.door.x = item.door.x;
      DataManager.Instance.door.y = item.door.y;
      DataManager.Instance.door.direction = item.door.direction;
      DataManager.Instance.door.state = item.door.state;

      // 恢复敌人状态
      for (let i = 0; i < DataManager.Instance.enemies.length; i++) {
          const enemy = item.enemies[i];
          DataManager.Instance.enemies[i].x = enemy.x;
          DataManager.Instance.enemies[i].y = enemy.y;
          DataManager.Instance.enemies[i].direction = enemy.direction;
          DataManager.Instance.enemies[i].state = enemy.state;
      }

      // 恢复爆炸物状态
      for (let i = 0; i < DataManager.Instance.bursts.length; i++) {
        const burst = item.bursts[i];
        DataManager.Instance.bursts[i].x = burst.x;
        DataManager.Instance.bursts[i].y = burst.y;
        DataManager.Instance.bursts[i].state = burst.state;
      }
      for (let i = 0; i < DataManager.Instance.spikes.length; i++) {
        const one = item.spikes[i];
        DataManager.Instance.spikes[i].x = one.x;
        DataManager.Instance.spikes[i].y = one.y;
        DataManager.Instance.spikes[i].count = one.count;
        DataManager.Instance.spikes[i].type = one.type;
      }
    }
  }
}


